package utils

import chisel3._

object RegNextA {

  def apply[T <: Data](reset: Reset, next: T): T = {
    dontTouch(reset)
    withReset((~reset.asBool).asAsyncReset)(RegNext(next))
  }

  def apply[T <: Data](reset: Reset, next: T, init: T): T = {
    dontTouch(reset)
    withReset((~reset.asBool).asAsyncReset)(RegNext(next, init))
  }
}

object RegInitA {

  def apply[T <: Data](reset:Reset, next: T, init: T): T = {
    dontTouch(reset)
    withReset((~reset.asBool).asAsyncReset)(RegNext(next, init))
  }

  def apply[T <: Data](reset:Reset, init: T): T = {
    dontTouch(reset)
    withReset((~reset.asBool).asAsyncReset)(RegInit(init))
  }

}

object RegNextWithEnableA {

  def apply[T <: Data](reset: Reset, en: Bool, next: T): T = {
    dontTouch(reset)
    val reg = withReset((~reset.asBool).asAsyncReset)(Reg(next.cloneType))
    when(en){
      reg := next
    } .otherwise{
      reg := reg
    }
    reg
  }

  def apply[T <: Data](reset: Reset, en: Bool, next: T, init: T): T = {
    dontTouch(reset)
    val reg = withReset((~reset.asBool).asAsyncReset)(RegInit(init))
    when(en){
      reg := next
    } .otherwise{
      reg := reg
    }
    reg
  }

}

object RegNextWithEnableClearA {
  def apply[T <: Data](reset: Reset, en: Bool, clear: Bool, next: T, init: T): T = {
    dontTouch(reset)
    val reg = withReset((~reset.asBool).asAsyncReset)(RegInit(init))
    when(clear){
      reg := init
    } .elsewhen(en){
      reg := next
    } .otherwise{
      reg := reg
    }
    reg
  }
}
